package controllers

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"image/png"
	"time"

	// "github.com/kataras/iris/errors"
	"github.com/pquerna/otp"
	"github.com/pquerna/otp/totp"
	"github.com/sirupsen/logrus"

	"learn-otp/models"
)

type UserController struct {
	BaseController
}

func (c *UserController) GetAllUser() {
	obj := c.GetString("obj")

	var data map[string]interface{}
	if err := json.Unmarshal([]byte(obj), &data); err != nil {
		c.writeError(err)
		return
	}
	pageIndex := int64(data["pageIndex"].(float64))
	pageSize := int64(data["pageSize"].(float64))
	accountName := data["accoutName"].(string)
	appName := data["appName"].(string)

	count, users, err := userDao.GetUsers(accountName, appName, pageIndex, pageSize)
	if err != nil {
		c.writeError(err)
		return
	}

	c.Data["json"] = Response{
		Data:    users,
		Total:   count,
		Success: true,
	}

	c.ServeJSON()
}

func (c *UserController) GetUser() {
	id, err := c.GetInt64("id")
	if err != nil {
		c.writeError(err)
		return
	}

	user, err := userDao.GetUser(id)
	if err != nil {
		c.writeError(err)
		return
	}

	c.Data["json"] = Response{
		Data:    user,
		Success: true,
	}

	c.ServeJSON()
}

func (c *UserController) SaveUser() {
	obj := c.GetString("obj")
	logrus.Info("input params: ", obj)

	var user models.User
	err := json.Unmarshal([]byte(obj), &user)
	if err != nil {
		c.writeError(err)
		return
	}

	if user.Id == 0 {
		err = userDao.AddUser(&user)
	} else {
		err = userDao.UpdateUser(&user)
	}

	if err != nil {
		c.writeError(err)
		return
	}

	c.Data["json"] = Response{
		Success: true,
	}

	c.ServeJSON()
}

func (c *UserController) DeleteUser() {
	id, err := c.GetInt64("id")
	if err != nil {
		c.writeError(err)
		return
	}

	logrus.Info("input params: ", id)

	err = userDao.DeleteUser(id)
	if err != nil {
		c.writeError(err)
		return
	}

	c.Data["json"] = Response{
		Success: true,
	}

	c.ServeJSON()
}

func (c *UserController) CreateOTP() {
	id, err := c.GetInt64("id")
	if err != nil {
		c.writeError(err)
		return
	}

	user, err := userDao.GetUser(id)
	if err != nil {
		c.writeError(err)
		return
	}

	key, err := totp.Generate(totp.GenerateOpts{
		Issuer:      "gxsugon",
		AccountName: user.AccountName,
		Algorithm:   otp.AlgorithmSHA1,
		SecretSize:  20,
	})

	// Convert TOTP key into a PNG
	var buf bytes.Buffer
	img, err := key.Image(200, 200)
	if err != nil {
		c.writeError(err)
		return
	}
	png.Encode(&buf, img)

	user.Secret = key.Secret()
	user.Qrcode = "data:image/png;base64," + base64.StdEncoding.EncodeToString(buf.Bytes())

	userDao.UpdateOTP(id, user.Secret, user.Qrcode)

	c.Data["json"] = Response{
		Data:    user,
		Success: true,
	}

	c.ServeJSON()
}

func (c *UserController) CheckOTP() {
	id, err := c.GetInt64("id")
	if err != nil {
		c.writeError(err)
		return
	}
	passCode := c.GetString("passCode")
	if passCode == "" {
		//err := errors.New("pass code is null")
		c.writeError(err)
		return
	}

	user, err := userDao.GetUser(id)
	if err != nil {
		c.writeError(err)
		return
	}

	ok, err := totp.ValidateCustom(passCode, user.Secret, time.Now(), totp.ValidateOpts{
		Digits:    otp.DigitsSix,
		Algorithm: otp.AlgorithmSHA1,
	})
	if err != nil {
		c.writeError(err)
		return
	}

	c.Data["json"] = Response{
		Success: ok,
	}

	c.ServeJSON()
}
